#include "StdAfx.h"
#include "ContentParser.h"

#include <algorithm>
#include <json/json.h>

CContentParser::CContentParser( CGridCtrl& listCtrl )
//////////////////////////////////////////////////////////////////////////
// control
: _parent( 0 )
, m_ListCtrl( listCtrl )
//////////////////////////////////////////////////////////////////////////
// flag
, _propSetted( false )
//////////////////////////////////////////////////////////////////////////
// property
, _rowStart( 0 )
, _rowEnd( 0 )
, _rowStep( 0 )
, _colStart( 0 )
, _colEnd( 0 )
, _colStep( 0 )
, _rowHeight( 25 )
, _colWidth( 50 )
, _colPrecision( 0 )
, _rowPrecision( 0 )
, _inputPrecision( 0 )
{
}

CContentParser::~CContentParser(void)
{
}

void CContentParser::setParent( HWND parent )
{
	_parent = parent;
}

void CContentParser::setPropertySetted()
{
	_propSetted = true;
	m_ListCtrl.SetGridLineColor( Convert( _gridLineColor ) );
}

void CContentParser::OnCreate()
{
	m_ListCtrl.EnableDragAndDrop( FALSE );
	m_ListCtrl.SetRowResize( FALSE );
	m_ListCtrl.SetColumnResize( FALSE );
	m_ListCtrl.SetHeaderSort( FALSE );
	m_ListCtrl.SetFrameFocusCell( FALSE );
}

void CContentParser::FillListCtrl(void)
{
	if( !IsWindow( m_ListCtrl.m_hWnd ) || !_propSetted )
	{
		return;
	}

	vector< CString > rows, cols;
	double colValue = _colStart;
	bool colSort = _colStart < _colEnd;
	while( colSort ? colValue <= _colEnd : colValue >= _colEnd )
	{
		cols.push_back( FormatHeadString( colValue ) );
		colValue += _colStep;
	}

	double rowValue = _rowStart;
	bool rowSort = _rowStart < _rowEnd;
	while( rowSort ? rowValue <= _rowEnd : rowValue >= _rowEnd )
	{
		rows.push_back( FormatHeadString( rowValue ) );
		rowValue += _rowStep;
	}

	m_ListCtrl.SetColumnCount( (int)cols.size() + 1 );
	m_ListCtrl.SetRowCount( (int)rows.size() + 1 );
	m_ListCtrl.SetFixedColumnCount( 1 );
	m_ListCtrl.SetFixedRowCount( 1 );

	m_ListCtrl.SetItemBkColour( 0, 0, Convert( _colHeaderColor ) );
	m_ListCtrl.SetColumnWidth( 0, 80 );
	m_ListCtrl.SetRowHeight( 0, 20 );

	for ( int i = 1; i < m_ListCtrl.GetColumnCount(); ++i )
	{
		m_ListCtrl.SetItemData( 0, i, _colPrecision );
		m_ListCtrl.SetItemText( 0, i, cols[i - 1] );
		m_ListCtrl.SetItemBkColour( 0, i, Convert( _colHeaderColor ) );
		m_ListCtrl.SetColumnWidth( i, _colWidth );
	}
	for ( int i = 1; i < m_ListCtrl.GetRowCount(); ++i )
	{
		m_ListCtrl.SetItemData( i, 0, _rowPrecision );
		m_ListCtrl.SetItemText( i, 0, rows[i - 1] );
		m_ListCtrl.SetItemBkColour( i, 0, Convert( _rowHeaderColor ) );
		m_ListCtrl.SetRowHeight( i, _rowHeight );
	}

	for ( int i = 0; i < m_ListCtrl.GetRowCount(); ++i )
	{
		for ( int j = 0; j < m_ListCtrl.GetColumnCount(); ++j )
		{
			m_ListCtrl.SetItemFormat( i, j, DT_CENTER|DT_VCENTER|DT_SINGLELINE );
		}
	}

	for ( int i = 1; i < m_ListCtrl.GetRowCount(); ++i )
	{
		for ( int j = 1; j < m_ListCtrl.GetColumnCount(); ++j )
		{
			m_ListCtrl.SetItemBkColour( i, j, ( i % 2 == 0 ) ? Convert( _evenLineColor ) : Convert( _oddLineColor ) );
			m_ListCtrl.SetItemData( i, j, _inputPrecision );
		}
	}
	{
		vector< SelectData >::iterator it = _selectData.begin(), itEnd = _selectData.end();
		for ( ; it != itEnd; ++it )
		{
			m_ListCtrl.SetItemText( it->row + 1, it->col + 1, FormatString( it->value ) );
		}
	}

	{
		vector< InitData >::iterator it = _initData.begin(), itEnd = _initData.end();
		for ( ; it != itEnd; ++it )
		{
			if( !it->enable )
			{
				m_ListCtrl.SetItemState( it->row + 1, it->col + 1, m_ListCtrl.GetItemState( it->row + 1, it->col + 1 ) | GVIS_READONLY);
				m_ListCtrl.SetItemBkColour( it->row + 1, it->col + 1, Convert( _disableColor ) );
			}
		}
	}

	m_ListCtrl.GetDefaultCell( FALSE, FALSE )->SetSelectBackClr( Convert( _selectedColor ) );
	m_ListCtrl.SetItemText( 0, 0, _title );
}

void CContentParser::FillSelectValues()
{
	_selectData.clear();
	for ( int i = 1; i < m_ListCtrl.GetRowCount(); ++i )
	{
		for ( int j = 1; j < m_ListCtrl.GetColumnCount(); ++j )
		{
			CString strText = m_ListCtrl.GetItemText( i, j );
			if( !strText.IsEmpty() )
			{
				SelectData data;
				data.row = i - 1;
				data.col = j - 1;
				data.value = _wtof( strText );
				_selectData.push_back( data );
			}
		}
	}
}

void CContentParser::ParseContent( const CString& value )
{
	CStringA strContent( value );
	Json::Reader reader;
	Json::Value root;
	if( !reader.parse( (LPCSTR)strContent, root ) )
	{
		return;
	}

	Json::Value::iterator it = root.begin(), itEnd = root.end();
	for ( ; it != itEnd; ++it )
	{
		Json::Value node( *it );

		SelectData selectData;
		InitData initData;
		initData.row = node["x"].asInt();
		initData.col = node["y"].asInt();

		Json::Value::Members members( node.getMemberNames() );
		Json::Value::Members::iterator it = members.begin(), itEnd = members.end();
		for ( ; it != itEnd; ++it )
		{
			string name( *it );
			if( name == "x" || name == "y" || name == "v" )
			{
				continue;
			}
			initData._extras[ name.c_str() ] = node[ name.c_str() ].asCString();
		}

		initData.enable = ( node.isMember( "goodsid" ) ) && ( node[ "goodsid" ].asString() != "" );

		if( node.isMember( "v" ) )
		{
			selectData.row = initData.row;
			selectData.col = initData.col;
			selectData.value = node["v"].asDouble();
			_selectData.push_back( selectData );
		}
		_initData.push_back( initData );
	}
}

CString CContentParser::GenerateContent()
{
	Json::FastWriter writer;
	Json::Value root;

	vector< SelectData >::iterator it = _selectData.begin(), itEnd = _selectData.end();
	for ( ; it != itEnd; ++it )
	{
		Json::Value pair;
		pair["x"] = it->row;
		pair["y"] = it->col;
		pair["v"] = it->value;

		InitData* initData = FindInitData( it->row, it->col );
		if( initData != NULL )
		{
			InitData::Extras::iterator it = initData->_extras.begin(), itEnd = initData->_extras.end();
			for ( ; it != itEnd; ++it )
			{
				pair[ (LPCSTR)it->first ] = (LPCSTR)it->second;
			}
		}
		root.append( pair );
	}
	CStringA strContent( writer.write( root ).c_str() );
	return CStringW( strContent );
}

InitData* CContentParser::FindInitData( int row, int col )
{
	vector< InitData >::iterator it = _initData.begin(), itEnd = _initData.end();
	for ( ; it != itEnd; ++it )
	{
		if( it->row == row && it->col == col )
		{
			return &*it;
		}
	}
	return NULL;
}

COLORREF CContentParser::Convert( const CString& str )
{
	int index = str.Find( L',' );
	if( index == -1 )
	{
		return RGB( 255,255,255 );
	}

	CString r = str.Left( index ).Trim();

	CString leave = str.Right( str.GetLength()- index - 1 );
	index = leave.Find( L"," );
	if( index == -1 )
	{
		return RGB( 255,255,255 );
	}

	CString g = leave.Left( index ).Trim();
	CString b = leave.Right( leave.GetLength() - index - 1 );

	return RGB( _wtoi( r ), _wtoi( g ), _wtoi( b ) );
}

CString CContentParser::FormatHeadString( double value )
{
	CString strValue( FormatString( value ) );

	if( !strValue.IsEmpty() && strValue[0] != '-' )
	{
		strValue = L"+" + strValue;
	}
	return strValue;
}

CString CContentParser::FormatString( double value )
{
	CString strValue;
	strValue.Format( L"%f", value );

	return strValue;
}